package com.fsc.controller;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.fsc._enum.ReturnEnum;
import com.fsc.entity.ResultWrapper;
import com.fsc.entity.domain.LoginInfo;
import com.fsc.entity.dto.ChangePasswordDTO;
import com.fsc.entity.dto.CommonLoginDto;
import com.fsc.entity.dto.ModifyDTO;
import com.fsc.entity.dto.RegisterDTO;
import com.fsc.entity.vo.LoginUserVO;
import com.fsc.service.LoginInfoService;
import com.fsc.util.FileUtil;
import com.fsc.util.OssUtil;
import com.fsc.util.SMSUtil;
import com.fsc.util.ValidateCodeUtil;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Objects;
/**
 * 用户登录注册
 */
@RestController
@RequestMapping("/user/")
public class UserSignController {
    @Autowired
    private LoginInfoService loginInfoService;
    @Resource
    private RedisTemplate<String, Object> redisStringTemplate;
    @Resource
    private RedisTemplate<String, byte[]> redisByteTemplate;


    /**
     * 登录
     * @param commonLoginDto 登录信息
     * @return 登录成功返回用户信息
     */
    @PostMapping("login")
    public ResultWrapper<LoginUserVO> Login(@RequestBody CommonLoginDto commonLoginDto) {
        String column=null;
        String username=commonLoginDto.getUsername();
        String password=commonLoginDto.getPassword();
        if(loginInfoService.query().eq("username",username).eq("password",password).exists()){
           column="username";
        }else
        if(loginInfoService.query().eq("id",username).eq("password",password).exists()){
            column="id";
        }else
        if(loginInfoService.query().eq("phone",username).eq("password",password).exists()){
            column="phone";
        }
        if(column!=null){
            int id=loginInfoService.query().eq(column,username).eq("password",password).one().getId();
            StpUtil.login(id);
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            LoginInfo loginInfo = loginInfoService.query().eq("id", id).one();
            LoginUserVO loginUserVO = LoginUserVO.builder()
                    .userId(loginInfo.getId())
                    .username(loginInfo.getUsername())
                    .phone(loginInfo.getPhone())
                    .role(loginInfo.getRole())
                    .iconUrl(loginInfo.getIconUrl())
                    .token(tokenInfo.getTokenValue())
                    .build();


            return ResultWrapper.success(ReturnEnum.SUCCESS_LOGIN,loginUserVO);
        }
        return ResultWrapper.fail(ReturnEnum.ACCOUNT_PASSWORD_WRONG);
    }


    /**
     * 验证码登录
     * @param phone 手机号
     * @param code 验证码
     * @return 登录成功返回用户信息
     */
    @GetMapping("code-login")
    public ResultWrapper<LoginUserVO> codeLogin(@RequestParam("phone") String phone, @RequestParam("code") String code) {
        //从redis中取出验证码
        String redisCode= (String) redisStringTemplate.opsForValue().get(phone);
        //判断验证码跟手机号是否匹配以及正确
        if(redisCode!=null&&redisCode.equals(code)){
            //登录
            LoginInfo loginInfo=loginInfoService.query().eq("phone",phone).one();
            StpUtil.login(loginInfo.getId());
            //登录成功验证失效
            redisStringTemplate.delete(phone);
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            LoginUserVO loginUserVO = LoginUserVO.builder()
                    .userId(loginInfo.getId())
                    .username(loginInfo.getUsername())
                    .phone(phone)
                    .role(loginInfo.getRole())
                    .iconUrl(loginInfo.getIconUrl())
                    .token(tokenInfo.getTokenValue())
                    .build();
            return ResultWrapper.success(ReturnEnum.SUCCESS_LOGIN,loginUserVO);
        }
        return ResultWrapper.fail(ReturnEnum.PHONE_CODE_WRONG);

    }
    /**
     * 获取验证码
     * @param phone 手机号
     * @return 获取验证码成功
     */
    @GetMapping("get-code")
    public ResultWrapper<Integer> getCode(@RequestParam("phone") String phone) {boolean exist = loginInfoService.query().eq("phone", phone).exists();
        if (!exist) {
            return ResultWrapper.fail(ReturnEnum.PHONE_NOT_EXIST);
        }
        String  signName = "阿里云短信测试";
        String templateCode = "SMS_154950909";
        //生成4位验证码
        String code= ValidateCodeUtil.generateValidateCode(4).toString();
        //将验证码存入redis,五分钟有效
        System.out.println(code);
        redisStringTemplate.opsForValue().set(phone,code, Duration.ofMinutes(5));
        //调用阿里云提供的短信服务发送到手机
        SMSUtil.sendMessage(signName,templateCode, phone, code);
        return ResultWrapper.success(ReturnEnum.SUCCESS_SEND_CODE);
    }
    /**
     * 退出登录
     * @return 退出登录成功
     */
    @GetMapping("logout")
    public ResultWrapper<String> logout() {
        StpUtil.logout();
        return ResultWrapper.success(ReturnEnum.SUCCESS_LOGOUT);
    }
    /**
     * 注册
     * @param registerDTO 注册信息
     * @return 注册成功返回用户id
     */
    @PostMapping("register")
    public ResultWrapper<Integer> register(@Validated @RequestBody  RegisterDTO registerDTO) throws IOException {
        String phone=registerDTO.getPhone();
        String username=registerDTO.getUsername();
        if(loginInfoService.query().eq("phone",phone).exists()){
           return ResultWrapper.fail(ReturnEnum.PHONE_USER_EXIST);
        }
        if(loginInfoService.query().eq("username",username).exists()){
            return ResultWrapper.fail(ReturnEnum.USERNAME_USER_EXIST);
        }
        String iconUrl = registerDTO.getIconUrl();
        if(Boolean.FALSE.equals(redisByteTemplate.hasKey(iconUrl))){
            return ResultWrapper.fail(ReturnEnum.UPLOAD_FAIL);
        }
        OssUtil.uploadImage(redisByteTemplate.opsForValue().get(iconUrl),iconUrl);
        LoginInfo loginInfo = LoginInfo.builder()
                .username(registerDTO.getUsername())
                .phone(registerDTO.getPhone())
                .password(registerDTO.getPassword())
                .role(Integer.parseInt(registerDTO.getRole()))
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .iconUrl(registerDTO.getIconUrl())
                .build();
        redisByteTemplate.delete(iconUrl);
        loginInfoService.save(loginInfo);
        Integer id=loginInfoService.query().eq("phone",phone).eq("username",username).one().getId();
        return ResultWrapper.success(ReturnEnum.SUCCESS_REGISTER,id);
    }
    /**
     * 上传图片
     * @param file 图片文件
     * @return 上传成功返回图片url
     */
    @PostMapping("upload-pic")
    public ResultWrapper<String> uploadPic( @RequestParam("file") MultipartFile file) throws IOException {
        String fileOriginName = file.getOriginalFilename();
        if(!FileUtil.isImage(fileOriginName)){
            return ResultWrapper.fail(ReturnEnum.UPLOAD_FAIL, "请上传正确图片格式");
        }
        String fileName = FileUtil.generateImageName(fileOriginName);
        //将图片存入redis,三分钟有效
        redisByteTemplate.opsForValue().set(fileName,file.getBytes(),Duration.ofMinutes(3));
        return ResultWrapper.success(ReturnEnum.SUCCESS_UPLOAD,fileName);
    }
    /**
     * 修改密码
     * @param changePasswordDTO 修改密码信息
     * @return 修改密码成功
     */
    @PostMapping("change-password")
    public ResultWrapper<String> changePassword(@RequestBody @Validated ChangePasswordDTO changePasswordDTO) {
        String phone=changePasswordDTO.getPhone();
        String code=changePasswordDTO.getCode();

        if(!Objects.equals(redisStringTemplate.opsForValue().get(phone), code)){
            return ResultWrapper.fail(ReturnEnum.PHONE_CODE_WRONG);
        }
        redisStringTemplate.delete(phone);
        loginInfoService.update().eq("phone",phone).set("password",changePasswordDTO.getPassword()).update();
        return ResultWrapper.success("修改密码成功");
    }

    /**
     * 修改用户信息
     * @param modifyDTO 修改信息
     * @return 修改成功返回用户信息
     */
    @PostMapping("modify")
    public ResultWrapper<LoginUserVO> modify(@Validated @RequestBody ModifyDTO modifyDTO) throws IOException {
        String iconUrl = modifyDTO.getIconUrl();
        if(Boolean.FALSE.equals(redisByteTemplate.hasKey(iconUrl))){
            return ResultWrapper.fail(ReturnEnum.UPLOAD_FAIL);
        }
        OssUtil.uploadImage(redisByteTemplate.opsForValue().get(iconUrl),iconUrl);
        LoginUserVO loginUserVO = loginInfoService.updateUser(modifyDTO);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        loginUserVO.setToken(tokenInfo.getTokenValue());
        redisByteTemplate.delete(iconUrl);
        return ResultWrapper.success(ReturnEnum.SUCCESS,loginUserVO);
    }
}

